home *** CD-ROM | disk | FTP | other *** search
- /*{{{}}}*/
- /*{{{ #includes*/
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <limits.h>
- #ifndef NO_GETOPT_H
- # include <getopt.h>
- #endif
- #include <errno.h>
- #include <dirent.h>
- #include <signal.h>
- #include <string.h>
- #include <unistd.h>
- #include <stdlib.h>
- #include <stdio.h>
- #include <pwd.h>
- #include <time.h>
-
- #define BIND_CONST
- #include <h/keys.h>
- #include <h/envvar_str.h>
- #include <h/os.h>
-
- #include <lib/ori_add_lib.h>
- #include <lib/ori_rc_lib.h>
- #include <lib/ori_re_lib.h>
- #include <h/rcformat.h>
- /*}}} */
-
- /*{{{ variables*/
- #define START_DEPTH 255
- /*{{{ fold-marks*/
- char fold_open_str[FOLD_TAG_LENGTH+1]=BEGIN_STANDARD;
- char fold_close_str[FOLD_TAG_LENGTH+1]=END_STANDARD;
- char fold_file_str[FOLD_TAG_LENGTH+1]=FILE_STANDARD;
- char fold_line_str[FOLD_TAG_LENGTH+1]=LINE_STANDARD;
- /*}}} */
- /*{{{ for commandline-options*/
- char const *keybase=0;
- char const *ori_path=ORIGAMI_RC_PATH;
- int always=0;
- int mark_no_perm=0;
- #ifdef REGEXP
- char const *match_str="";
- regex_t preg_match;
- char const *no_match_str="";
- regex_t preg_no_match;
- int aborted=0;
- regmatch_t ma[1];
- #endif
- /*}}} */
- int single=0;
- int depth=START_DEPTH;
- uid_t user;
- gid_t group;
- int long_format=0;
- /*}}} */
-
- /*{{{ error_exit*/
- void error_exit(char const * const m)
- {
- fputs(m,stderr);
- exit(1);
- }
- /*}}} */
- /*{{{ set_other_mark*/
- /*{{{ parse rcfile*/
- int rc_file_parser(char const * const mark_mode,FILE * const rcfile)
- {
- readtags input;
-
- rc_get_w(rcfile);
- while ((input=rc_get_c(rcfile))!=RC_ENDE && input!=RC_BIND)
- { switch (input) {
- /*{{{ termalias*/
- case RC_TERMALIAS:
- { int ch;
-
- while ((ch=rc_get_c(rcfile)) && ch!=EOF)
- do ch=rc_get_c(rcfile); while (ch && ch!=EOF);
- do ch=rc_get_c(rcfile); while (ch && ch!=EOF);
- continue;
- }
- /*}}} */
- /*{{{ usermodestrings*/
- case RC_MODE: {
- int lg;
-
- rc_get_c(rcfile);
- lg=rc_get_w(rcfile);
- if (lg)
- rc_skip_cw(rcfile,lg,0);
- lg=rc_get_w(rcfile);
- if (lg)
- rc_skip_cw(rcfile,lg,0);
- continue;
- }
- /*}}} */
- /*{{{ macroload/init*/
- case RC_LOADMACRO:
- case RC_INITMACRO:
- { int lg;
-
- rc_get_w(rcfile);
- lg=rc_get_w(rcfile);
- rc_skip_cw(rcfile,0,lg);
- continue;
- }
- /*}}} */
- /*{{{ consts*/
- case RC_CONST:
- rc_skip_cw
- ( rcfile,
- BIND_NAME_LEN+NO_OCL_CMD_OPTS*(2*BIND_NAME_LEN+2),
- RCC_SIZE
- );
- continue;
- /*}}} */
- /*{{{ comment/os-extension*/
- case RC_COMMENT:
- case RC_OS_EXTENSION:
- while ((input=rc_get_c(rcfile)) && input!=EOF);
- continue;
- /*}}} */
- /*{{{ mouse-tab*/
- case RC_M_TAB:
- rc_skip_cw(rcfile,0,rc_get_w(rcfile));
- continue;
- /*}}} */
- /*{{{ marks*/
- case RC_MARKS:
- { char name[FOLD_PATTERN_LEN];
- int i;
-
- /*{{{ read stored name*/
- for (i=0;i<(FOLD_PATTERN_LEN-1);i++)
- name[i]=rc_get_c(rcfile);
- name[FOLD_PATTERN_LEN-1]='\0';
- /*}}} */
- if (!strcmp(mark_mode,name))
- /*{{{ reset mark-strings*/
- { for (i=0;i<FOLD_TAG_LENGTH;i++) fold_open_str[i]=rc_get_c(rcfile);
- for (i=0;i<FOLD_TAG_LENGTH;i++) fold_line_str[i]=rc_get_c(rcfile);
- for (i=0;i<FOLD_TAG_LENGTH;i++) fold_file_str[i]=rc_get_c(rcfile);
- for (i=0;i<FOLD_TAG_LENGTH;i++) fold_close_str[i]=rc_get_c(rcfile);
- return(0);
- }
- /*}}} */
- else
- /*{{{ overread the data*/
- { rc_skip_cw(rcfile,4*FOLD_TAG_LENGTH,0);
- continue;
- }
- /*}}} */
- }
- /*}}} */
- /*{{{ keydef,macset,set,strings,comp-dat*/
- case RC_DEFKEY:
- case RC_MAC_SET:
- case RC_CHARSET:
- case RC_STRINGS:
- case RC_REF_COMP_STR:
- break;
- /*}}} */
- /*{{{ error!*/
- default:
- fputs("incorrect rc-data,",stderr);
- return(1);
- /*}}} */
- }
- break;
- }
- fputs("no matching marks found, ",stderr);
- return(1);
- }
- /*}}} */
-
- int set_other_mark(char const * const mark_mode)
- {
- char const *keyfile;
- char base[_POSIX_PATH_MAX];
- int ok;
- FILE *rcfile;
-
- /*{{{ get base for rc file*/
- if (keybase)
- strcpy(base,keybase);
- else
- sprintf(base,BASENAMEF,"origami");
- /*}}} */
- /*{{{ search for file in path list*/
- keyfile=get_system_filename
- ( ori_path,
- base,
- RC_ENDING,
- (char*)0
- );
- /*}}} */
- if (!keyfile[0] || !(rcfile=fopen(keyfile,"r")))
- { fputs("no "RC_ENDING"-file found,",stderr);
- ok=1;
- }
- else
- { ok=rc_file_parser(mark_mode,rcfile);
- fclose(rcfile);
- }
-
- return (ok);
- }
- /*}}} */
- /*{{{ show_modes*/
- char *show_modes(struct stat const * const f)
- { static char coding[256];
- char *s=coding;
-
- /*{{{ decode filetype*/
- /*{{{ dir*/
- if (S_ISDIR(f->st_mode))
- *s++='d';
- /*}}} */
- /*{{{ block special*/
- # ifdef S_ISBLK
- else if (S_ISBLK(f->st_mode))
- *s++='b';
- # endif
- /*}}} */
- /*{{{ character special*/
- # ifdef S_ISCHR
- else if (S_ISCHR(f->st_mode))
- *s++='c';
- # endif
- /*}}} */
- /*{{{ symbolic link*/
- # ifdef S_ISLNK
- else if (S_ISLNK(f->st_mode))
- *s++='l';
- # endif
- /*}}} */
- /*{{{ fifo*/
- # ifdef S_ISFIFO
- else if (S_ISFIFO(f->st_mode))
- *s++='p';
- # endif
- /*}}} */
- /*{{{ network special*/
- # ifdef S_ISNWK
- else if (S_ISNWK(f->st_mode))
- *s++='n';
- # endif
- /*}}} */
- /*{{{ socket*/
- # ifdef S_ISSOCK
- else if (S_ISSOCK(f->st_mode))
- *s++='s';
- # endif
- /*}}} */
- /*{{{ file*/
- else if (S_ISREG(f->st_mode))
- *s++='-';
- /*}}} */
- /*{{{ default unknown*/
- else
- *s++='?';
- /*}}} */
- /*}}} */
- /*{{{ decode owner/group/others permissions*/
- /*{{{ owner*/
- # ifdef S_IRUSR
- /*{{{ read access permission for owner*/
- if (S_IRUSR&f->st_mode)
- *s++='r';
- else
- *s++='-';
- /*}}} */
- # endif
- # ifdef S_IWUSR
- /*{{{ write access permission for owner*/
- if (S_IWUSR&f->st_mode)
- *s++='w';
- else
- *s++='-';
- /*}}} */
- # endif
- # ifdef S_IXUSR
- /*{{{ execute/search access permission for owner*/
- if (S_IXUSR&f->st_mode)
- *s++='x';
- else
- *s++='-';
- /*}}} */
- # endif
- /*}}} */
- /*{{{ group*/
- # ifdef S_IRGRP
- /*{{{ read access permission for group*/
- if (S_IRGRP&f->st_mode)
- *s++='r';
- else
- *s++='-';
- /*}}} */
- # endif
- # ifdef S_IWGRP
- /*{{{ write access permission for group*/
- if (S_IWGRP&f->st_mode)
- *s++='w';
- else
- *s++='-';
- /*}}} */
- # endif
- # ifdef S_IXGRP
- /*{{{ execute/search access permission for group*/
- if (S_IXGRP&f->st_mode)
- *s++='x';
- else
- *s++='-';
- /*}}} */
- # endif
- /*}}} */
- /*{{{ others*/
- # ifdef S_IROTH
- /*{{{ read access permission for others*/
- if (S_IROTH&f->st_mode)
- *s++='r';
- else
- *s++='-';
- /*}}} */
- # endif
- # ifdef S_IWOTH
- /*{{{ write access permission for others*/
- if (S_IWOTH&f->st_mode)
- *s++='w';
- else
- *s++='-';
- /*}}} */
- # endif
- # ifdef S_IXOTH
- /*{{{ execute/search access permission for others*/
- if (S_IXOTH&f->st_mode)
- *s++='x';
- else
- *s++='-';
- /*}}} */
- # endif
- /*}}} */
- /*}}} */
- # ifndef NO_POSIX_STAT
- /*{{{ number of bytes and time*/
- { struct passwd const *x=getpwuid(f->st_uid);
- char t[27];
-
- strcpy(t,ctime(&f->st_mtime));
- t[16]='\0';
- sprintf(s," %8s%9ld %s",x?x->pw_name:"",(long)f->st_size,t+4);
- while (*s) s++;
- }
- /*}}} */
- # else
- NO_POSIX_STAT
- # endif
- *s++=' ';
- *s='\0';
- return(coding);
- }
- /*}}} */
- /*{{{ path_get*/
- void path_get
- ( int const absolut,
- char * const dir,
- char const * const cur,
- char const * const ent
- )
- {
- *dir='\0';
- if (!absolut || !getcwd(dir,_POSIX_PATH_MAX))
- { if (!*ent || !IS_ROOT(ent))
- strcpy(dir,cur);
- else
- *dir='\0';
- if (*dir && *ent)
- strcat(dir,PATH_SEP);
- strcat(dir,ent);
- if (absolut)
- printf("getcwd(%s): %s\n",dir,strerror(errno));
- }
- }
- /*}}} */
- /*{{{ dirhandle*/
- /*{{{ dir_ent_cmp*/
- int dir_ent_cmp(const void *a, const void *b)
- {
- return(strcmp(*((char**)a),*((char**)b)));
- }
- /*}}} */
- /*{{{ forward for filehandle*/
- void filehandle
- ( int,
- char const * const name,
- char const * const dir,
- int const curr_depth
- );
- /*}}} */
-
- void dirhandle
- ( int absolut,
- char const * const name,
- char const * const dir,
- int const curr_depth,
- struct stat const * const buff
- )
- {
- if (curr_depth<=depth)
- /*{{{ recursion*/
- { char fn[_POSIX_PATH_MAX+1];
- DIR *dirptr;
-
- if (absolut)
- /*{{{ chdir and read*/
- { if (chdir(name))
- absolut=0;
- else
- strcpy(fn,CURR_DIR);
- }
- /*}}} */
- if (!absolut)
- /*{{{ relative, don't change dir, combine pathname for dir*/
- { if (!IS_ROOT(name))
- { strcpy(fn,dir);
- if (fn[0]) strcat(fn,PATH_SEP);
- }
- else
- fn[0]=0;
- strcat(fn,name);
- }
- /*}}} */
- if (fn[0])
- if ((dirptr=opendir(fn))) {
- /*{{{ can read the entries*/
- /*{{{ local variables*/
- char new_wd[_POSIX_PATH_MAX+1];
- struct dirent *ls;
- char **s;
- # define bl_size 128
- int count=0;
- int curr;
- int curr_size=bl_size;
- int marked_point=0;
- /*}}} */
-
- /*{{{ get buffer for dir-entries*/
- if (!(s=ORImalloc(curr_size*sizeof(char*))))
- error_exit("no memory\n");
- /*}}} */
- /*{{{ read the contents of the directory*/
- while ((ls=readdir(dirptr))) {
- /*{{{ expand entry-list*/
- if (count==curr_size) {
- char **old=s;
- int x=0;
-
- if (!(s=ORImalloc((curr_size+bl_size)*sizeof(char*))))
- error_exit("no memory\n");
- while (x<curr_size) {s[x]=old[x];x++;}
- ORIfree(old);
- curr_size+=bl_size;
- }
- /*}}} */
- /*{{{ get memory for entry*/
- if (!(s[count]=ORImalloc(strlen(ls->d_name)+1)))
- error_exit("no memory\n");
- /*}}} */
- strcpy(s[count++],ls->d_name);
- }
- /*}}} */
- qsort((void*)s,(size_t)count,(size_t)sizeof(char*),dir_ent_cmp);
- if (!single)
- printf("%s %s%s\n",
- fold_open_str,long_format?show_modes(buff):"",name);
- /*{{{ get new working directory*/
- path_get(absolut,new_wd,dir,name);
- /*}}} */
- /*{{{ handle all entries of the directory*/
- curr=0;
- while (curr<count) {
- if (strcmp(CURR_DIR,s[curr]) && (single || strcmp(PREV_DIR,s[curr]))) {
- /*{{{ maybe mark .???*/
- if (!marked_point && s[curr][0]=='.') {
- marked_point=1;
- printf("%s .xxx files\n",fold_open_str);
- }
- /*}}} */
- /*{{{ maybe endmark .???*/
- if (marked_point && s[curr][0]!='.') {
- marked_point=0;
- printf("%s\n",fold_close_str);
- }
- /*}}} */
- filehandle(absolut,s[curr],new_wd,curr_depth);
- ORIfree(s[curr]);
- }
- curr++;
- }
- /*}}} */
- if (marked_point) printf("%s\n",fold_close_str);
- if (!single) printf("%s\n",fold_close_str);
- ORIfree(s);
- closedir(dirptr);
- /*}}} */
- } else
- printf("cannot read this directory %s.\n",fn);
- else
- printf("%s cannot enter\n",name);
- if (absolut) chdir(dir);
- }
- /*}}} */
- else
- if (single)
- printf("%sF %s%s\n%sF %s%s%s\n%s\n",
- fold_open_str,long_format?show_modes(buff):"",name,
- fold_file_str,dir,PATH_SEP,name,
- fold_close_str);
- else
- printf("maxdepth reached for %s.\n",name);
- }
- /*}}} */
- /*{{{ filehandle*/
- void filehandle
- ( int absolut,
- char const * const name,
- char const * const dir,
- int const curr_depth
- )
- {
-
- # ifdef REGEXP
- if (curr_depth)
- if
- ( (*match_str && regexec(&preg_match,name,(size_t)0,ma,0)!=0)
- || (*no_match_str && regexec(&preg_no_match,name,(size_t)0,ma,0)==0)
- )
- return;
- # endif
- if (curr_depth<=depth)
- { struct stat buff;
- char fn[_POSIX_PATH_MAX+1];
-
- /*{{{ get filename for stat*/
- if (absolut)
- strcpy(fn,name);
- else
- { if (!IS_ROOT(name))
- { strcpy(fn,dir);
- if (fn[0]) strcat(fn,PATH_SEP);
- }
- else
- fn[0]='\0';
- strcat(fn,name);
- }
- /*}}} */
- if (stat(fn,&buff))
- printf("cannot stat %s=%s: %s.\n",name,name,strerror(errno));
- else {
- if ( ((buff.st_uid==user) && (S_IRUSR&buff.st_mode))
- || ((buff.st_gid==group) && (S_IRGRP&buff.st_mode))
- || (S_IROTH&buff.st_mode)
- || OS_READPERM(fn,&buff)
- || always )
- {
- /*{{{ handle a directory*/
- if (S_ISDIR(buff.st_mode))
- dirhandle(absolut,name,dir,curr_depth+1,&buff);
- /*}}} */
- /*{{{ handle a file*/
- if (S_ISREG(buff.st_mode)) {
- printf("%sF %s%s\n",
- fold_open_str,
- long_format?show_modes(&buff):"",
- name);
- printf("%sF %s%s%s\n",fold_file_str,dir,PATH_SEP,name);
- printf("%s\n",fold_close_str);
- }
- /*}}} */
- } else if (mark_no_perm)
- printf("no permission for %s\n",name);
- }
- }
- }
- /*}}} */
-
- /*{{{ main*/
- int main(int argc, char *argv[])
- { char call_path[_POSIX_PATH_MAX+1];
- int absolut=1;
- int no;
-
- user=geteuid();
- group=getegid();
- /*{{{ parse arguments*/
- { int c;
- char const *mark_mode=0;
-
- while ((c=getopt(argc,argv,"k:lm:hd:apM:srf:F:R:"))!=EOF)
- switch (c)
- {
- /*{{{ f*/
- case 'f':
- # ifdef REGEXP
- match_str=optarg;
- # endif
- break;
- /*}}} */
- /*{{{ F*/
- case 'F':
- # ifdef REGEXP
- no_match_str=optarg;
- # endif
- break;
- /*}}} */
- /*{{{ d*/
- case 'd':
- if (single) d_s_error:
- error_exit("d and s conflict\n");
- depth=atoi(optarg);
- if (depth<=0)
- { puts("nothing to do.");
- exit(0);
- }
- break;
- /*}}} */
- /*{{{ l*/
- case 'l':
- long_format=1;
- break;
- /*}}} */
- /*{{{ r*/
- case 'r': absolut=0;break;
- /*}}} */
- /*{{{ s*/
- case 's':
- if (depth!=START_DEPTH)
- goto d_s_error;
- single=1;
- depth=1;
- break;
- /*}}} */
- /*{{{ m*/
- case 'm': mark_mode=optarg;break;
- /*}}} */
- /*{{{ a*/
- case 'a': always=1;break;
- /*}}} */
- /*{{{ p*/
- case 'p': mark_no_perm=1;break;
- /*}}} */
- /*{{{ k*/
- case 'k': keybase=optarg;break;
- /*}}} */
- /*{{{ M*/
- case 'M':
- { char *s=optarg;
- int k;
-
- for (k=0;k<FOLD_TAG_LENGTH;)
- if (!(fold_open_str[k++]= *s++)) M_error:
- error_exit("invalid marks given\n");
- fold_open_str[FOLD_TAG_LENGTH]='\0';
- for (k=0;k<FOLD_TAG_LENGTH;)
- if (!(fold_file_str[k++]= *s++))
- goto M_error;
- fold_file_str[FOLD_TAG_LENGTH]='\0';
- for (k=0;k<FOLD_TAG_LENGTH;)
- if (!(fold_line_str[k++]= *s++))
- goto M_error;
- fold_line_str[FOLD_TAG_LENGTH]='\0';
- for (k=0;k<FOLD_TAG_LENGTH;)
- if (!(fold_close_str[k++]= *s++))
- goto M_error;
- fold_close_str[FOLD_TAG_LENGTH]='\0';
- if (*s)
- goto M_error;
- break;
- }
- /*}}} */
- /*{{{ R*/
- case 'R':
- ori_path=optarg;
- break;
- /*}}} */
- /*{{{ h and error*/
- default:
- case '?':
- fputs("dirfold: invalid option\n",stderr);
- case 'h':
- fputs
- ( "Usage:\tdirfold [-ahlpsr] [-d depth]"
- # ifdef REGEXP
- " [-f match]"
- # endif
- " [-k namebase]\n\t[-m markname]"
- # ifdef REGEXP
- " [-F nomatch]"
- # endif
- " [-M markpatterns] [-R "RC_ENDING"-path-list]\n\t[filename] ...\n",
- stderr
- );
- exit((c=='h')?0:1);
- /*}}} */
- }
- # ifdef REGEXP
- /*{{{ handle [no_]match string*/
- if (*match_str)
- /*{{{ compile*/
- { if
- ( regcomp
- ( &preg_match,
- match_str,
- USE_NOSUB(0)|REG_EXTENDED|USE_SUB_LIMIT(0,preg_match)
- )
- != 0
- )
- error_exit("dirfold: invalid match expression\n");
- }
- /*}}} */
- if (*no_match_str)
- /*{{{ compile*/
- { if
- ( regcomp
- ( &preg_no_match,
- no_match_str,
- USE_NOSUB(0)|REG_EXTENDED|USE_SUB_LIMIT(0,preg_match)
- )
- != 0
- )
- error_exit("dirfold: invalid no-match expression\n");
- }
- /*}}} */
- /*}}} */
- # endif
- /*{{{ no marks found*/
- if (mark_mode && set_other_mark(mark_mode))
- error_exit("dirfold: mark conflict\n");
- /*}}} */
- }
- /*}}} */
- path_get(absolut,call_path,"","");
- if (argv[no=optind])
- do
- filehandle(absolut,argv[no],call_path,0);
- while (argv[++no]);
- else
- filehandle(absolut,CURR_DIR,call_path,0);
- if (call_path[0])
- chdir(call_path);
- return(0);
- }
- /*}}} */
-